import shelve

from config import PATH_TO_SHELF
import packages
import nltk
from nltk.corpus import brown

import pronouncer


class _BaseTagger(object):
    """ """

    _simplify_tags = True
    _patterns = []
    _default_tag = 'N'

    def __init__(self):
        brown_sents = brown.tagged_sents(simplify_tags=self._simplify_tags)
        t0 = nltk.DefaultTagger(self._default_tag)
        t1 = nltk.RegexpTagger(self._patterns, backoff=t0)
        t2 = nltk.UnigramTagger(brown_sents, backoff=t1)
        self._tagger = nltk.BigramTagger(brown_sents, cutoff=2, backoff=t2)

    def tag(self, raw):
        """The tag method takes a string of user input and returns a list of lists of tuples.""" 
        pos_tags = []
        raw = raw.lower()
        sentences = nltk.sent_tokenize(raw)

        # tokens = [nltk.word_tokenize(sent) for sent in sentences]
        tokens = [pronouncer.tokenize(sent) for sent in sentences]

        for sentence in tokens:
            sentence_pos = self._tagger.tag(sentence)
            pos_tags.append(sentence_pos)
        return pos_tags

    @classmethod
    def factory(cls):
        shelf = shelve.open(PATH_TO_SHELF)
        if str(cls) not in shelf:
            shelf[str(cls)] = cls()
        instance = shelf[str(cls)]
        try:
            shelf.close()
        except IOError:
            pass
        return instance


class SimpleTagger(_BaseTagger):
    """This tagger uses Brown's simplified part of speech tag list."""

    # Specify Brown's simplified part of speech tag list:
    _simplify_tags = True

    _patterns = [
        (r'.*ing$',                 'VG'),  # gerunds
        (r'.*ed$',                  'VD'),  # simple past
        (r'.*es$',                  'V'),   # 3rd singular present
        (r'.*ould$',                'MD'),  # modals
        (r".*'s$",                  'N'),   # possessive nouns
        (r'.*s$',                   'N'),   # plural nouns
        (r'^-?[0-9]+(.[0-9]+)?$',   'CD'),  # cardinal numbers
        (r'.*',                     'N')    # nouns (default)
    ]

    _default_tag = 'N'


class FullTagger(_BaseTagger):
    """This tagger uses Brown's complete part of speech tag list."""

    # Specify Brown's complete part of speech tag list:
    _simplify_tags = False

    _patterns = [
        (r'.*ing$',                 'VBG'), # gerunds
        (r'.*ed$',                  'VBD'), # simple past
        (r'.*es$',                  'VBZ'), # 3rd singular present
        (r'.*ould$',                'MD'),  # modals
        (r'.*\'s$',                 'NN$'), # possessive nouns
        (r'.*s$',                   'NNS'), # plural nouns
        (r'^-?[0-9]+(.[0-9]+)?$',   'CD'),  # cardinal numbers
        (r'.*',                     'NN')   # nouns (default)
     ]

    _default_tag = 'NN'
